'''
Created on Jun 15, 2012

@author: thomas_dao
'''

from web import base
from web.base import BaseHandler
from web import urls, util, settings
from google.appengine.ext import ndb
import json, urllib
from webapp2 import uri_for
import logging
import feedparser
from entity.google_entity import GoogleUser


def request_token_url():
    scope = '%s %s %s' %(settings.GOOGLE_SCOPE_EMAIL_URL,
                         settings.GOOGLE_SCOPE_PROFILE_URL,
                         settings.GOOGLE_SCOPE_CONTACT_URL)
    
    request_token_url = "%s?response_type=code&client_id=%s&redirect_uri=%s&scope=%s" \
                        %(settings.GOOGLE_REQUEST_TOKEN_URL,
                          settings.GOOGLE_CLIENT_ID,
                          urllib.quote(uri_for('import-google-contact', _full=True)),
                          urllib.quote(scope))
    return request_token_url
    

class GoogleContactHandler(BaseHandler):
    """
    Follow closely with Google OAuth2 API, include three legs
    1) Request for user permission
    2) Authenticate app to receive access_token
    3) Retrieve user's data using received token
    
    It will look for existing GoogleUser by gmail. Otherwise,
    it will create one, and save the contacts data (name + email)
    """
    @ndb.synctasklet
    @base.user_required
    def get(self):
        code = self.request.params.get('code')
        if (code == None):
            # Step 1: Request for permission
            self.redirect(request_token_url())
        
        else:
            # Step 2: Authenticate app
            params = {}
            params['grant_type'] = 'authorization_code'
            params['client_id'] = settings.GOOGLE_CLIENT_ID
            params['redirect_uri'] = uri_for('import-google-contact', _full=True)
            params['client_secret'] = settings.GOOGLE_CLIENT_SECRET
            params['code'] = code
            content = yield util.post_url_async(settings.GOOGLE_REQUEST_ACCESS_TOKEN_URL,
                                                      urllib.urlencode(params), {})
            try:
                content = json.loads(content)
            except:
                self.redirect(request_token_url())
                return
                
            access_token = content.get('access_token')
            
            # Retrieve gmail and profile using retrieved access_token
            profile_url = '%s?access_token=%s' %(settings.GOOGLE_PROFILE_URL, access_token)
            content = yield util.get_url_async(profile_url)
            content = json.loads(content)
            email = content.get('email')
            name = content.get('name')

            # Look for existing google user
            # If not, create one            
            qry = GoogleUser.query(GoogleUser.gmail==email)
            existing_guser = qry.fetch(limit=1)
            if not existing_guser:
                # Retrieve contacts
                contact_url = settings.GOOGLE_CONTACT_URL %(email, access_token)
                # Parse the Atom in contact_url using feedparser
                content = feedparser.parse(contact_url)
                friend_list = []
                for entry in content.get('entries'):
                    gd_email = entry.get('gd_email')
                    if gd_email:
                        friend = {}
                        friend['email'] = gd_email.get('address')
                        friend['name'] = entry.get('gd_fullname')
                        friend_list.append(friend)
                        
                # Create new google_user
                google_user = GoogleUser()
                google_user.gmail = email
                google_user.name = name
                google_user.friend_list = friend_list
                google_user.user = util.get_current_user_key()
                google_user.put()
                
                self.response.write(json.dumps(util.ndb_to_dict(google_user)))
            
app = urls.app

def main():
    app.run()

if __name__ == '__main__':
    main()